package com.maple.admin.user.dao.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.maple.admin.misc.paging.dto.PagingParamsDTO;
import com.maple.admin.user.dao.IAccountDAO;
import com.maple.admin.user.dto.UserDTO;
import com.maple.admin.user.po.UserPO;

/**
 * @author luobenyu
 * @see https://stackoverflow.com/questions/26203446/spring-hibernate-could-not-obtain-transaction-synchronized-session-for-current
 * 
 */
@Repository
@Transactional
public class IAccountDAOImpl implements IAccountDAO {
	
	@Autowired
	private SessionFactory sessionFactory;
	
	/**
	 * result for single row
	 */
	private UserDTO user = new UserDTO();
	
	public UserDTO getUser() {
		return user;
	}

	public void setUser(UserDTO user) {
		this.user = user;
	}

	/**
	 * result for multiple rows
	 */
	private List<UserDTO> userList = new ArrayList<UserDTO>(); 

	public List<UserDTO> getUserList() {
		return userList;
	}

	public void setUserList(List<UserDTO> userList) {
		this.userList = userList;
	}

	public IAccountDAOImpl() {
		// TODO Auto-generated constructor stub
	}
	
	@Override
	public UserDTO queryUserByLoginName(String userName) throws IndexOutOfBoundsException {
		UserPO po = null;
		//
		Session session;
		StringBuffer hql = new StringBuffer("from UserPO u ");
		hql.append("where u.userName = :uName ");
		try {
			session = sessionFactory.getCurrentSession();
		} catch (HibernateException e) {
			// TODO Auto-generated catch block
			session = sessionFactory.openSession();
			e.printStackTrace();
		}
		Query q = session.createQuery(hql.toString());
		q.setString("uName", userName);
		try {
			po = (UserPO) q.list().get(0);
		} catch (IndexOutOfBoundsException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw e;
		}
		//
		BeanUtils.copyProperties(po, user);
		return user;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<UserDTO> queryPaginatedUsers(PagingParamsDTO paging) {
		// TODO Auto-generated method stub
		UserDTO tmpDto = new UserDTO();
		List<UserDTO> resultList = new ArrayList<UserDTO>();
		Session session;
		StringBuffer hql = new StringBuffer("from UserPO u ");
		try {
			session = sessionFactory.getCurrentSession();
		} catch (HibernateException e) {
			// TODO Auto-generated catch block
			session = sessionFactory.openSession();
			e.printStackTrace();
		}
		Query q = session.createQuery(hql.toString()).setCacheable(true);
		q.setFirstResult(paging.getPage());
		q.setMaxResults(paging.getRows());
		List<UserPO> tmpList = q.list();
		for(UserPO tmpPo : tmpList){
			BeanUtils.copyProperties(tmpPo, tmpDto);
			resultList.add(tmpDto);
			tmpDto = new UserDTO();
		}
		return resultList;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<UserDTO> queryAllUsers() {
		// TODO Auto-generated method stub
		UserDTO tmpDto = new UserDTO();
		List<UserDTO> resultList = new ArrayList<UserDTO>();
		//
		Session session;
		StringBuffer hql = new StringBuffer("from UserPO u ");
		try {
			session = sessionFactory.getCurrentSession();
		} catch (HibernateException e) {
			// TODO Auto-generated catch block
			session = sessionFactory.openSession();
			e.printStackTrace();
		}
		Query q = session.createQuery(hql.toString());
		List<UserPO> tmpList = q.list();
		for(UserPO tmpPo : tmpList){
			BeanUtils.copyProperties(tmpPo, tmpDto); 
			resultList.add(tmpDto);
			tmpDto = new UserDTO();
		}
		//
		return resultList;
	}

	@SuppressWarnings("unchecked")
	@Override
	public Boolean checkDuplicated(String userName) {
		// TODO Auto-generated method stub
		Boolean alreadyExists = Boolean.FALSE;
		//
		Session session;
		StringBuffer hql = new StringBuffer("from UserPO u ");
		hql.append("where u.userName =:userName ");
		try {
			session = sessionFactory.getCurrentSession();
		} catch (HibernateException e) {
			// TODO Auto-generated catch block
			session = sessionFactory.openSession();
			e.printStackTrace();
		}
		Query q = session.createQuery(hql.toString());
		q.setString("userName", userName);
		List<UserPO> tmpList = q.list();
		if(tmpList.size() > 0){
			alreadyExists =  Boolean.TRUE;
		}
		return alreadyExists;
	}

	@Override
	public UUID createUser(UserDTO newUser) {
		// TODO Auto-generated method stub
		UserPO origin = new UserPO();
		BeanUtils.copyProperties(newUser, origin);
		//
		Session session;
		try {
			session = sessionFactory.getCurrentSession();
		} catch (HibernateException e) {
			// TODO Auto-generated catch block
			session = sessionFactory.openSession();
			e.printStackTrace();
		}
		UUID createdID = (UUID) session.save(origin);
		session.flush();
		session.close();
		return createdID;
	}

}
